// 功能简单、接口不齐全的allocator -> 提供基本的内存分配、释放、构造和销毁功能
#ifndef _JJALLOC_
#define _JJALLOC_

#include <new>
#include <cstddef>
#include <cstdlib>
#include <climits>
#include <iostream>

using namespace std;

namespace JJ
{
    template <class T>
    inline T *_allocate(ptrdiff_t size, T *)
    {
        set_new_handler(0); // 设置new操作的异常处理函数为空，即不处理异常
        T *tmp = (T *)(::operator new((size_t)(size * sizeof(T)))); // 分配内存
        if (tmp == 0) // 内存分配失败
        {
            cerr << "out of memory" << endl;
            exit(1);
        }
        return tmp;
    }

    // 释放内存函数
    template <class T>
    inline void _deallocate(T *buffer)
    {
        ::operator delete(buffer);
    }

    // 在分配的内存上构造对象
    template <class T1, class T2>
    inline void _construct(T1 *p, const T2 &value)
    {
        new (p) T1(value);
    }

    // 销毁对象函数
    template <class T>
    inline void _destroy(T *ptr)
    {
        ptr->~T();
    }

    // 嵌套模板结构，用于类型转换
    template <class T>
    class allocator
    {
    public:
        typedef T value_type;
        typedef T* pointer;
        typedef const T* const_pointer;
        typedef T& reference;
        typedef const T& const_reference;
        typedef size_t size_type;
        typedef ptrdiff_t difference_type;

        template <class U>
        struct rebind
        {
            typedef allocator<U> other; // 转换后的分配器类型
        };

        pointer allocate(size_type n, const void* hint=0)
        {
            return _allocate((difference_type)n, (pointer)0);
        }

        void deallocate(pointer p, size_type n)
        {
            _deallocate(p);
        }

        void construct(pointer p, const T& value)
        {
            _construct(p, value);
        }

        void destroy(pointer p)
        {
            _destroy(p);
        }

        // 返回对象的地址
        pointer address(reference x)
        {
            return (pointer)&x;
        }

        // 返回const对象的地址
        const_pointer const_address(const_reference x)
        {
            return (const_pointer)&x;
        }

        // 返回可以分配到最大对象数量
        size_type max_size() const
        {
            return size_type(UINT_MAX/sizeof(T));
        }
    };

} // end of namespace JJ

#endif